package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.FieldAttrEntityExt;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.product.pojo.dto.ProductExplainDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.BusinessProductEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.CostAdjustEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionMaterielOutstockEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.product.ProductionOrderFinishProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderMaterielProductEnum;
import com.xbongbong.saas.enums.product.PurchaseProductEnum;
import com.xbongbong.saas.enums.product.TransferProductEnum;
import com.xbongbong.saas.enums.product.WorkOrderOutstockProductEnum;
import com.xbongbong.saas.model.FormConfigModel;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
public class ExplainHelp {

    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private AccuryHelp accuryHelp;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private ProFormHelp proFormHelp;

    public void getRelativeProductExplainsFromDB(String corpid, Map<String, FieldAttrEntity> nowProductExplainMap, Map<String, FieldAttrEntity> nowStockProductExplainMap) throws XbbException {
        if (corpid == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (nowProductExplainMap != null) {
            // 获取当前启用的产品字段解释
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("saasMark", 1);
            param.put("businessType", XbbRefTypeEnum.PRODUCT.getCode());
            List<PaasFormExplainEntity> formExplainList = paasFormExplainModel.list(param);
            if (!formExplainList.isEmpty()) {
                PaasFormExplainEntity paasFormExplainEntity = formExplainList.get(0);
                List<FieldAttrEntity> nowProductExplainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity entity : nowProductExplainList) {
                    nowProductExplainMap.put(entity.getSaasAttr(), entity);
                    if (Objects.equals(entity.getAttr(), ProductEnum.UNIT.getAttr())) {
                        nowProductExplainMap.put(SelectProductEnum.UNIT.getSaasAttr(), entity);
                    }
                }
            }
        }

        if (nowProductExplainMap != null && nowStockProductExplainMap != null) {
            // 获取当前启用的库存产品字段解释
            param.clear();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("saasMark", 1);
            param.put("businessType", XbbRefTypeEnum.STOCK_PRODUCT.getCode());
            List<PaasFormExplainEntity> stockProductExplainList = paasFormExplainModel.list(param);
            if (!stockProductExplainList.isEmpty()) {
                PaasFormExplainEntity paasFormExplainEntity = stockProductExplainList.get(0);
                List<FieldAttrEntity> nowStockProductExplainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity entity : nowStockProductExplainList) {
                    Integer isRedundant = entity.getIsRedundant();
                    if (Objects.equals(isRedundant, 0)) {
                        // 系统字段，key为saasAttr
                        nowProductExplainMap.put(entity.getSaasAttr(), entity);
                    } else {
                        // 自定义字段，key为attr
                        nowStockProductExplainMap.put(entity.getAttr(), entity);
                    }
                }
            }
        }
    }

    /**
     * 选择产品的字段解释，具体业务具体逻辑处理
     *
     * @param productFieldAttrEntity 字段解释实体
     * @param xbbRefTypeEnum 业务类型枚举 如：XbbRefTypeEnum.BOM_BILL
     * @param attr 外层字段的attr 如：BomBillEnum.PRODUCT.getAttr()
     * @author chaoxiong.lei
     * @date 20:49 2019/2/25
     * @since v1.0
     * @return 是否放入解释集合中
     **/
    public Boolean dealWithSelectProductExplains(FieldAttrEntity productFieldAttrEntity, XbbRefTypeEnum xbbRefTypeEnum, String attr) {
        if (productFieldAttrEntity == null || xbbRefTypeEnum == null) {
            return false;
        }
        Boolean result = true;
        String saasAttr = productFieldAttrEntity.getSaasAttr();
        switch (xbbRefTypeEnum) {
            case BOM_BILL:
                if (Objects.equals(attr, BomBillEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.ATTRITION_RATE.getSaasAttr().equals(saasAttr)) {
                    // 成品产品没有损耗率字段
                    result = false;
                } else if (Objects.equals(attr, BomBillEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(0);
                }
                break;
            case SALES_OPPORTUNITY:
                if (RelativeProductEnum.UNIT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.UNIT));
                } else if (RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SALE_DISCOUNT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                    productFieldAttrEntity.setRequired(1);
                } else if (RelativeProductEnum.SALE_PRODUCT_PRICE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                    productFieldAttrEntity.setRequired(1);
                }
                break;
            case QUOTATION:
                if (RelativeProductEnum.UNIT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.UNIT));
                } else if (RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SALE_DISCOUNT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SALE_PRODUCT_PRICE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.PRICE_YUAN));
                } else if (RelativeProductEnum.SUBTOTAL.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.SUBTOTAL_YUAN));
                }
                break;
            case CONTRACT:
                if (RelativeProductEnum.UNIT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.UNIT));
                } else if (RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SALE_DISCOUNT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SALE_PRODUCT_PRICE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.MEMO.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                } else if (RelativeProductEnum.SUBTOTAL.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setRequired(1);
                }
                break;
            case PRODUCTION_ORDER:
                if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.WAREHOUSE.getSaasAttr().equals(saasAttr)) {
                    result = false;
                } else if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(ProductionOrderFinishProductEnum.NUM.getAttrName());
                    result = true;
                } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(ProductionOrderMaterielProductEnum.NUM.getAttrName());
                    result = true;
                } else if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.ATTRITION_RATE.getSaasAttr().equals(saasAttr)) {
                    result = false;
                } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())
                        && RelativeProductEnum.WAREHOUSE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(ProductionMaterielOutstockEnum.WAREHOUSE_ID.getAttrName());
                } else if (Objects.equals(attr, ProductionOrderEnum.MATERIEL.getAttr())
                        && RelativeProductEnum.ATTRITION_RATE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(0);
                }
                break;
            case INVENTORY:
                if (Objects.equals(attr, InventoryEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.ACTUAL_AMOUNT));
                }
                break;
            case TRANSFER:
                if (Objects.equals(attr, TransferEnum.PRODUCTS.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(TransferProductEnum.NUM.getAttrName());
                }
                break;
            case OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case OTHER_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
                if (Objects.equals(attr, OutstockEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(WorkOrderOutstockProductEnum.NUM.getAttrName());
                }
                if (Objects.equals(attr, OutstockEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.COST.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(WorkOrderOutstockProductEnum.COST.getAttrName());
                }
                break;
            case INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
                if (Objects.equals(attr, InstockEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.STOCK_NUM));
                }
                if (Objects.equals(attr, InstockEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.COST.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.STOCK_COST));
                }
                if (Objects.equals(attr, InstockEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.BATCH.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setFieldType(FieldTypeEnum.TEXT.getType());
                }
                break;
            case PURCHASE:
                // 采购合同产品采购单价可以编辑
                if (Objects.equals(attr, PurchaseEnum.PRODUCT.getAttr()) && RelativeProductEnum.PRODUCT_PRICE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                    productFieldAttrEntity.setAttrName(PurchaseProductEnum.PURCHASE_PRICE.getAttrName());
                } else if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.PURCHASE_NUM));
                } else if (Objects.equals(attr, ProductionOrderEnum.PRODUCT.getAttr())
                        && RelativeProductEnum.SUBTOTAL.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(PurchaseProductEnum.SUBTOTAL.getAttrName());
                }
                break;
            case ASSEMBLE:
                if (Objects.equals(attr, AssembleEnum.IN_PRODUCTS.getAttr()) && RelativeProductEnum.BATCH.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setFieldType(1);
                }
                break;
            case COST_ADJUST:
                if (Objects.equals(attr, CostAdjustEnum.PRODUCT.getAttr()) && RelativeProductEnum.UNIT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setFieldType(FieldTypeEnum.COMBO.getType());
                }
                break;
            case WORK_ORDER:
                if (RelativeProductEnum.UNIT.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(CommonConstant.UNIT));
                } else if (RelativeProductEnum.NUM.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setEditable(1);
                    productFieldAttrEntity.setRequired(1);
                } else if (RelativeProductEnum.PRODUCT_PRICE.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setRequired(1);
                } else if (RelativeProductEnum.PRODUCT_NO.getSaasAttr().equals(saasAttr)) {
                    productFieldAttrEntity.setRequired(1);
                }
            default:
                break;
        }
        return result;
    }

    public List<FieldAttrEntity> getRelativeProductExplainList(List<RelativeProductEnum> businessProductEnumList, Map<String, FieldAttrEntity> nowProductExplainMap,
                                                               Map<String, FieldAttrEntity> nowStockProductExplainMap, XbbRefTypeEnum xbbRefTypeEnum, String attr) {
        List<FieldAttrEntity> relativeProductExplains = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (RelativeProductEnum relativeProductEnum : businessProductEnumList) {
            switch (relativeProductEnum) {
                // 产品解释中不放图片
                case THUMBNAIL:
                    continue;
                default:
                    break;
            }
            // 系统字段
            String saasAttr = relativeProductEnum.getSaasAttr();
            FieldAttrEntity entity = nowProductExplainMap.get(saasAttr);
            if (Objects.equals(relativeProductEnum, RelativeProductEnum.PRODUCT_PRICE) || Objects.equals(relativeProductEnum, RelativeProductEnum.SALE_PRODUCT_PRICE) ||
                    Objects.equals(relativeProductEnum, RelativeProductEnum.SUBTOTAL) || Objects.equals(relativeProductEnum, RelativeProductEnum.SALE_SUBTOTAL)) {
                entity = nowProductExplainMap.get(ProductEnum.PRICE.getSaasAttr());
            }
            if (entity != null) {
                Integer visible = entity.getVisible();
                Integer isOpen = entity.getIsOpen();
                if (Objects.equals(visible, 0) || Objects.equals(isOpen, 0)) {
                    // 字段未启用
                    continue;
                }
            }
            // 产品成本字段saasAttr转为productCost，不能在枚举里直接改，因为要和产品的saasAttr匹配
            if (Objects.equals(relativeProductEnum, RelativeProductEnum.COST)) {
                saasAttr = StringConstant.PRODUCT_COST;
            }
            FieldAttrEntity fieldAttrEntity = new FieldAttrEntity();
            // 这里不用paas那边的attr，特殊字段特殊处理，用saasAttr
            fieldAttrEntity.setAttr(saasAttr);
            fieldAttrEntity.setAttrName(relativeProductEnum.getAttrName());
            fieldAttrEntity.setSaasAttr(saasAttr);
            fieldAttrEntity.setFieldType(relativeProductEnum.getFieldType());
            fieldAttrEntity.setIsRedundant(0);
            fieldAttrEntity.setSort(relativeProductEnum.getSort());
            fieldAttrEntity.setEditable(relativeProductEnum.getEditable());
            fieldAttrEntity.setRequired(relativeProductEnum.getRequired());
            if (entity != null) {
                // 库存产品的required要实时获取，产品相关字段的也实时获取了，不过没有影响，产品相关字段是不能编辑的
                fieldAttrEntity.setRequired(entity.getRequired());
                fieldAttrEntity.setAccuracy(entity.getAccuracy());
                fieldAttrEntity.setItems(entity.getItems());
            }
            // 采购合同的产品采购单价精度为产品成本的精度
            if(XbbRefTypeEnum.PURCHASE == xbbRefTypeEnum && RelativeProductEnum.PRODUCT_PRICE == relativeProductEnum) {
                entity = nowProductExplainMap.get(ProductEnum.COST.getSaasAttr());
                if(entity != null) {
                    fieldAttrEntity.setAccuracy(entity.getAccuracy());
                }
            }
            // 数量的小数精度使用库存数量的精度
            if(RelativeProductEnum.NUM == relativeProductEnum) {
                entity = nowProductExplainMap.get(ProductEnum.STOCK.getSaasAttr());
                if(entity != null) {
                    fieldAttrEntity.setAccuracy(entity.getAccuracy());
                }
            }

            // 具体业务具体处理
            Boolean shouldPutInList = dealWithSelectProductExplains(fieldAttrEntity, xbbRefTypeEnum, attr);

            if (shouldPutInList) {
                relativeProductExplains.add(fieldAttrEntity);
            }
        }
        // 增加库存产品的自定义字段
        if (nowStockProductExplainMap != null) {
            for (FieldAttrEntity entity : nowStockProductExplainMap.values()) {
                if (XbbRefTypeEnum.INVENTORY == xbbRefTypeEnum
                        || XbbRefTypeEnum.TRANSFER == xbbRefTypeEnum
                        || XbbRefTypeEnum.ASSEMBLE == xbbRefTypeEnum
                        || XbbRefTypeEnum.INSTOCK == xbbRefTypeEnum
                        || XbbRefTypeEnum.OUTSTOCK == xbbRefTypeEnum) {
                    if (Objects.equals(entity.getVisible(), 1)) {
                        relativeProductExplains.add(entity);
                    }
                }
            }
        }
        return relativeProductExplains;
    }

    /**
     * 获取关联产品的表头
     *
     * @param xbbRefTypeEnum 业务枚举
     * @param corpid 公司id
     * @param attr 选择产品控件的attr
     * @author chaoxiong.lei
     * @date 14:50 2019/3/20
     * @since v1.0
     * @return java.util.List<FieldAttrEntity> 产品解释表头
     **/
    public List<FieldAttrEntityExt> getSelectProductExplains(XbbRefTypeEnum xbbRefTypeEnum, String corpid, String attr) throws XbbException {
        // 用于存放当前启用的产品模板解释的map
        Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, FieldAttrEntity> nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, nowStockProductExplainMap);

        // 获取关联产品需要展示的字段
        BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCode(xbbRefTypeEnum.getCode());
        List<FieldAttrEntity> relativeProductExplains = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (businessProductEnum != BusinessProductEnum.UNKNOW) {
            List<RelativeProductEnum> businessProductEnumList = businessProductEnum.getList();
            relativeProductExplains = getRelativeProductExplainList(businessProductEnumList,nowProductExplainMap, nowStockProductExplainMap,
                    xbbRefTypeEnum, attr);
        }

        List<FieldAttrEntityExt> fieldAttrEntityExtList = new ArrayList<>();
        for (FieldAttrEntity fieldAttrEntity : relativeProductExplains) {
            FieldAttrEntityExt fieldAttrEntityExt = new FieldAttrEntityExt();
            BeanUtil.copyProperties(fieldAttrEntity, fieldAttrEntityExt);
            // 小数精度
            String fieldAttrEntityAttr = fieldAttrEntityExt.getAttr();
            if(Objects.equals(fieldAttrEntityAttr, RelativeProductEnum.SALE_DISCOUNT.getSaasAttr())
                    || Objects.equals(fieldAttrEntityAttr, RelativeProductEnum.ATTRITION_RATE.getSaasAttr())) {
                fieldAttrEntityExt.setAccuracy(BasicConstant.TWO);
            }
            if (Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.PURCHASE) &&
                    (Objects.equals(fieldAttrEntityAttr, RelativeProductEnum.SUBTOTAL.getSaasAttr()) || Objects.equals(fieldAttrEntityAttr, RelativeProductEnum.PRODUCT_PRICE.getSaasAttr()))) {
                // 采购合同的采购单价和小计的精度使用产品成本的精度
                FieldAttrEntity costFieldEntity = nowProductExplainMap.get(ProductEnum.COST.getSaasAttr());
                if (costFieldEntity != null) {
                    fieldAttrEntityExt.setAccuracy(costFieldEntity.getAccuracy());
                }
            }
            fieldAttrEntityExtList.add(fieldAttrEntityExt);
        }

        return fieldAttrEntityExtList;
    }

    /**
     * 新建编辑时格式化选择产品控件中的产品解释字段
     *
     * @param fieldAttrEntity 产品字段解释实体
     * @param xbbRefTypeEnum 业务类型枚举，如：bom单选择产品：XbbRefTypeEnum.BOM_BILL
     * @param corpid 公司id
     * @param fromPage
     * @param unitNoEdit
     * @author chaoxiong.lei
     * @Date 20:52 2019/2/25
     * @since v1.0
     **/
    public void formatSelectProductExplains(FieldAttrEntity fieldAttrEntity, XbbRefTypeEnum xbbRefTypeEnum, String corpid, int fromPage, boolean unitNoEdit) throws XbbException {
        if (fieldAttrEntity == null || xbbRefTypeEnum == null || corpid == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        Integer fieldType = fieldAttrEntity.getFieldType();
        if (!Objects.equals(fieldType, FieldTypeEnum.SELECT_PRODUCT.getType())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        // 选择产品字段
        List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
        SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
        saasParticularAttributePoJo = saasParticularAttributePoJo != null ? saasParticularAttributePoJo : new SaasParticularAttributePoJo();
        String attr = fieldAttrEntity.getAttr();
        List<FieldAttrEntityExt> relativeProductExplains = getSelectProductExplains(xbbRefTypeEnum, corpid, attr);
        Map<String, FieldAttrEntityExt> relativeMap = new HashMap<>(relativeProductExplains.size());
        relativeProductExplains.forEach(item -> relativeMap.put(item.getAttr(), item));
        Iterator<? extends FieldAttrEntity> iterator = subExplainList.iterator();
        Boolean isJxcUse = true;
        if (Objects.equals(xbbRefTypeEnum,XbbRefTypeEnum.REFUND)){
            isJxcUse = paasAppModel.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
        }
        while (iterator.hasNext()) {
            FieldAttrEntity item = iterator.next();
            if (Objects.equals(ProductEnum.UNIT.getAttr(), item.getAttr())) {
                if (BasicConstant.ONE == fromPage) {
                    item.setEditable(1);
                }
                if (unitNoEdit) {
                    item.setMultiUnitNoEdit(1);
                }
                if (relativeMap.containsKey(item.getSaasAttr())) {
                    item.setItems(relativeMap.get(item.getSaasAttr()).getItems());
                }else if (!Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.ORI_STOCK)){
                    //期初解释不存在不启用字段
                    iterator.remove();
                }
            }else if (Objects.equals(SelectProductEnum.NUM.getAttr(), item.getAttr()) && Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.ORI_STOCK)){
                // 处理期初关联产品数量精度
                accuryHelp.setAccuracy(corpid,item);
            }else if (Objects.equals(SelectProductEnum.SOURCE_DOC.getAttr(),item.getAttr()) && !isJxcUse){
                iterator.remove();
            } else if (XbbRefTypeEnum.isDistributorHasProductBusinessType(xbbRefTypeEnum.getCode()) && Objects.equals(fieldAttrEntity.getDistributorMark(), DistributorMarkEnum.DISTRIBUTOR.getCode()) && Objects.equals(SelectProductEnum.NUM.getAttr(), item.getAttr())) {
                item.setIntegerOnly(1);
            } else if(Objects.equals(SelectProductEnum.PRODUCT.getAttr(), item.getAttr()) && Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.CONTRACT)){
                //新增可用库存量
                List<LinkedAttrPoJo> linkedAttrList=item.getLinkInfo().getLinkedAttr();
                List<LinkedAttrPoJo> stockPoJoList=linkedAttrList.stream().filter(p ->Objects.equals(p.getAttr(),ProductEnum.STOCK.getAttr()) ).collect(Collectors.toList());
                if (!stockPoJoList.isEmpty()){
                    LinkedAttrPoJo stockAttr=stockPoJoList.get(0);
                    LinkedAttrPoJo availableStockAttr= (LinkedAttrPoJo) CloneUtil.deepClone(stockAttr);
                    availableStockAttr.setAttr("availableStock");
                    availableStockAttr.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.AVAILABLE_STOCK));
                    availableStockAttr.setEditable(1);
                    linkedAttrList.add((linkedAttrList.indexOf(stockAttr)+1),availableStockAttr);
                }
            }
        }
        fieldAttrEntity.getSubForm().setItems(subExplainList);
        saasParticularAttributePoJo.setProductExplains(relativeProductExplains);
        fieldAttrEntity.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
    }

    /**
     *
     * @param productExplainDTO
     * @return
     * @throws XbbException
     */
    public List<FieldAttrEntityExt> getSelectProductExplains(ProductExplainDTO productExplainDTO) throws XbbException {
        String corpid = productExplainDTO.getCorpid();
        // 用于存放当前启用的产品模板解释的map
        Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, FieldAttrEntity> nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, nowStockProductExplainMap);

        XbbRefTypeEnum xbbRefTypeEnum = productExplainDTO.getXbbRefTypeEnum();
        Integer targetCode = productExplainDTO.getTargetCode();
        // 获取关联产品需要展示的字段
        BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCodeAndTargetCode(xbbRefTypeEnum.getCode(), targetCode);
        List<FieldAttrEntity> relativeProductExplains = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (businessProductEnum != BusinessProductEnum.UNKNOW) {
            List<RelativeProductEnum> businessProductEnumList = new ArrayList<>(businessProductEnum.getList());
            relativeProductExplains = getRelativeProductExplainList(businessProductEnumList,nowProductExplainMap, nowStockProductExplainMap,
                    xbbRefTypeEnum, productExplainDTO.getAttr());
        }

        int showSalePrice = 0;
        if (Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.OUTSTOCK) && Objects.equals(targetCode, XbbRefTypeEnum.CONTRACT.getCode())) {
            FormConfigEntity formConfigEntity = formConfigModel.getEntityByBusinessType(corpid, xbbRefTypeEnum.getCode(), FormConfigEnum.OUTSTOCK_DISPLAY_SALE_PRICE.getConfig());
            if (Objects.nonNull(formConfigEntity) && Objects.equals(formConfigEntity.getConfigValue(), "1")) {
                showSalePrice = 1;
            }
        }

        List<FieldAttrEntityExt> resultList = new ArrayList<>();
        for (FieldAttrEntity fieldAttrEntity : relativeProductExplains) {
            FieldAttrEntityExt fieldAttrEntityExt = new FieldAttrEntityExt();
            BeanUtil.copyProperties(fieldAttrEntity, fieldAttrEntityExt);
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(attr, RelativeProductEnum.SALE_PRODUCT_PRICE.getSaasAttr()) || Objects.equals(attr, RelativeProductEnum.SALE_SUBTOTAL.getSaasAttr())
                    || Objects.equals(attr, RelativeProductEnum.PRODUCT_PRICE.getSaasAttr()) || Objects.equals(attr, RelativeProductEnum.SALE_DISCOUNT.getSaasAttr())) {
                fieldAttrEntityExt.setShowSalePrice(showSalePrice);
            }
            // 小数精度
            if(Objects.equals(attr, RelativeProductEnum.SALE_DISCOUNT.getSaasAttr()) || Objects.equals(attr, RelativeProductEnum.ATTRITION_RATE.getSaasAttr())) {
                fieldAttrEntityExt.setAccuracy(BasicConstant.TWO);
            }
            resultList.add(fieldAttrEntityExt);
        }

        return resultList;
    }

    public List<FieldAttrEntity> handleExplain(List<FieldAttrEntity> explainList, List<String> fieldList, PaasFormEntityExt paasFormEntityExt) throws XbbException {
        List<FieldAttrEntity> list = new ArrayList<>();
        if (explainList == null || fieldList == null) {
            return list;
        }
        Map<String, List<String>> fieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> resultList = new ArrayList<>();
        if (Objects.nonNull(fieldList)) {
            fieldList.forEach(item->{
                if (item.contains(StringConstant.POINT)) {
                    String[] attrArray = item.split("\\.");
                    String attr = attrArray[0];
                    String subAttr = attrArray[1];
                    resultList.add(attr);
                    if (fieldMap.containsKey(attr)) {
                        List<String> subFieldList = fieldMap.get(attr);
                        subFieldList.add(subAttr);
                        fieldMap.put(attr, subFieldList);
                    } else {
                        List<String> subFieldList = new ArrayList<>();
                        subFieldList.add(subAttr);
                        fieldMap.put(attr, subFieldList);
                    }
                } else {
                    resultList.add(item);
                }
            });
        }
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            String attr = fieldAttrEntity.getAttr();

            if (resultList.contains(attr)) {
                if (!ShowTypeEnum.listShow(fieldAttrEntity.getShowType())){
                    continue;
                }
                if (Objects.equals(fieldAttrEntity.getVisible(), 1)) {
                    // 字段可见才返回
                    if (ExplainUtil.isSubForm(fieldAttrEntity.getFieldType())) {
                        List<? extends FieldAttrEntity> subExplain = fieldAttrEntity.getSubForm().getItems();
                        Iterator<? extends FieldAttrEntity> iterator = subExplain.iterator();
                        while (iterator.hasNext()) {
                            FieldAttrEntity jsonObject = iterator.next();
                            List<String> subFieldList = fieldMap.get(attr);
                            // 子表单内字段不为空
                            String subAttr = jsonObject.getAttr();
                            if (CollectionsUtil.isNotEmpty(subFieldList) && !subFieldList.contains(subAttr)) {
                                iterator.remove();
                                continue;
                            }
                        }
                        if (CollectionsUtil.isNotEmpty(subExplain)) {
                            list.add(fieldAttrEntity);
                        }
                    } else {
                        fieldAttrEntity.setItems(proFormHelp.setItem(fieldAttrEntity, paasFormEntityExt));
                        list.add(fieldAttrEntity);
                    }
                }
            }
        }
        return list;
    }
}
